package com.colorlight.cloud.gateway.api.message.constraint.basics;


import com.colorlight.cloud.gateway.api.annotation.*;
import com.colorlight.cloud.gateway.api.constants.GatewayConstants;
import com.colorlight.cloud.gateway.api.message.constraint.basics.object.Trans;
import com.colorlight.cloud.gateway.api.message.interceptor.trans.TransFromProtoInterceptor;
import com.google.protobuf.Descriptors;
import com.google.protobuf.MessageOrBuilder;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.*;

import static com.colorlight.cloud.gateway.api.annotation.method.PercentInvoke.percentInvokeFromProto;


/**
 * J java 对象 P 为Proto转Java 对象
 *
 * @author Demon
 */
@Slf4j
public class DefaultTransFromProtoRealize {
	private static final List<TransFromProtoInterceptor> TRANS_FROM_PROTO_INTERCEPTOR_LIST =
			new ArrayList<>(4);
	
	static {
		TRANS_FROM_PROTO_INTERCEPTOR_LIST.add(GatewayConstants.BASE_TRANS_FROM_PROTO_INTERCEPTOR);
		TRANS_FROM_PROTO_INTERCEPTOR_LIST.add(GatewayConstants.ENUM_TRANS_FROM_PROTO_INTERCEPTOR);
		TRANS_FROM_PROTO_INTERCEPTOR_LIST.add(GatewayConstants.OBJECT_TRANS_FROM_PROTO_INTERCEPTOR);
		TRANS_FROM_PROTO_INTERCEPTOR_LIST.add(GatewayConstants.COLLECTION_TRANS_FROM_PROTO_INTERCEPTOR);
	}
	
	public static <J extends Trans<J, P>, P extends MessageOrBuilder> J protoToObject(
			P sourceObject, J targetObject) {
		// 直接赋值 不需要构建对象
		// 全部属性获取
		Field[] declaredFields = targetObject.getClass().getDeclaredFields();
		// todo 这个地方有点问题，如果是枚举类型的，值为0，那么allFields会没有这个
		Map<Descriptors.FieldDescriptor, Object> allFields = sourceObject.getAllFields();
		Descriptors.Descriptor descriptorForType = sourceObject.getDescriptorForType();
		for (Field field : declaredFields) {
			// 设置字段可访问
			field.setAccessible(true);
			// 获取方法 目标类型
			Class<?> type = field.getType();
			try {
				// 注解方式处理别名
				String realName = field.getName();
				name annotation = field.getAnnotation(name.class);
				String finalName = realName;
				if (annotation != null) {
					finalName = annotation.value();
				}
				//finalName 为协议定义名称
				Descriptors.FieldDescriptor networkType = descriptorForType.findFieldByName(finalName);
				
			
				
				Optional<TransFromProtoInterceptor> first =
						TRANS_FROM_PROTO_INTERCEPTOR_LIST.stream().filter(e -> e.isInterceptor(type)).findFirst();
				TransFromProtoInterceptor transFromProtoInterceptor =
						first.orElseThrow(() -> new IllegalArgumentException("未知类型处理" + type.getName()));
				//对非基本类型做空属性判断
				if (!GatewayConstants.BASE_TRANS_FROM_PROTO_INTERCEPTOR.equals(transFromProtoInterceptor)) {
					if (Objects.isNull(networkType)) {
						log.warn("异常的获取属性, finalName: {}, type: {}", finalName, type);
					} else if (!allFields.containsKey(networkType)) {
						continue;
					}
				}
				// proto获取属性的方法名
				String protoMethodName = transFromProtoInterceptor.getProtoMethodName(finalName);
				
				// 获取需要注入参数
				Object value = transFromProtoInterceptor.getValue(protoMethodName, sourceObject);
				//基本类型的处理
				if (GatewayConstants.BASE_TRANS_FROM_PROTO_INTERCEPTOR.equals(transFromProtoInterceptor)) {
					//参数纠正1
					defaultValue valueAnnotation = field.getAnnotation(defaultValue.class);
					if (valueAnnotation != null) {
						String[] defaultValues = valueAnnotation.value();
						for (String s : defaultValues) {
							if (value.toString().equals(s)) {
								value = null;
								break;
							}
						}
					}
					if (value == null) {
						continue;
					}
					// 参数纠正 2
					percent percent = field.getAnnotation(percent.class);
					if (percent != null) {
						int divisor = percent.divisor();
						value = percentInvokeFromProto(value, divisor);
					}
					
					modelRevision modelRevision = field.getAnnotation(modelRevision.class);
					if (modelRevision != null) {
						value = modelRevisionInvoke(value);
					}
				}
				
				/**
				 *  当前对象的注入方法名 不受{@link name}注解影响
				 */
				String methodName = transFromProtoInterceptor.getMethodName(realName);
				// 获取输入对象 传入对象与 value部分时候不是同一类型
				Class<?> inputClass = transFromProtoInterceptor.getInputClass(field);
				// 赋值
				transFromProtoInterceptor.addAttribute(targetObject, value, inputClass, methodName);
			} catch (Exception e) {
				//防止单个消息的转化失败导致 整条消息都崩溃
				log.warn("对象解析异常,原始属性信息.属性信息{}", type.getName());
			}
			
		}
		return targetObject;
	}
	
	private static Object modelRevisionInvoke(Object o) {
		if (null == o) {
			return null;
		}
		Object target = null;
		if (o instanceof String) {
			String model = (String) o;
			char c = model.charAt(0);
			if(c == 'c' || c == 'a'){
				target = Character.toUpperCase(c) + model.substring(1);
			}
			
		}
		return target;
	}
}
